/*
 * @Author: lixu lixu@puchigames.com
 * @Date: 2025-09-18 11:40:00
 * @LastEditors: lixu lixu@puchigames.com
 * @LastEditTime: 2025-09-18 11:40:00
 * @FilePath: /go-helper/ixLog/utils.go
 * @Description: 日志工具函数和便捷API
 */

package ixLog

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

// 全局默认日志器
var (
	defaultLogger Logger
	defaultOnce   sync.Once
	globalMutex   sync.RWMutex
)

// initDefaultLogger 初始化默认日志器
func initDefaultLogger() {
	// 从环境变量加载配置
	envConfig := LoadConfigFromEnv()
	var config *Config
	if envConfig != nil {
		config = envConfig
	} else {
		config = DefaultConfig()
	}

	logger, err := NewLogger()
	_ = config // 避免未使用变量警告
	if err != nil {
		// 如果创建失败，使用最简单的配置
		logger, _ = NewLogger(
			WithLevel(INFO),
			WithConsoleOutput(true),
		)
	}

	defaultLogger = logger
}

// GetDefaultLogger 获取默认日志器
func GetDefaultLogger() Logger {
	defaultOnce.Do(initDefaultLogger)
	globalMutex.RLock()
	defer globalMutex.RUnlock()
	return defaultLogger
}

// SetDefaultLogger 设置默认日志器
func SetDefaultLogger(logger Logger) {
	globalMutex.Lock()
	defer globalMutex.Unlock()
	defaultLogger = logger
}

// 全局便捷方法
func Trace(args ...interface{}) {
	GetDefaultLogger().Trace(args...)
}

func Tracef(format string, args ...interface{}) {
	GetDefaultLogger().Tracef(format, args...)
}

func Debug(args ...interface{}) {
	GetDefaultLogger().Debug(args...)
}

func Debugf(format string, args ...interface{}) {
	GetDefaultLogger().Debugf(format, args...)
}

func Info(args ...interface{}) {
	GetDefaultLogger().Info(args...)
}

func Infof(format string, args ...interface{}) {
	GetDefaultLogger().Infof(format, args...)
}

func Warn(args ...interface{}) {
	GetDefaultLogger().Warn(args...)
}

func Warnf(format string, args ...interface{}) {
	GetDefaultLogger().Warnf(format, args...)
}

func Error(args ...interface{}) {
	GetDefaultLogger().Error(args...)
}

func Errorf(format string, args ...interface{}) {
	GetDefaultLogger().Errorf(format, args...)
}

func Fatal(args ...interface{}) {
	GetDefaultLogger().Fatal(args...)
}

func Fatalf(format string, args ...interface{}) {
	GetDefaultLogger().Fatalf(format, args...)
}

// 全局便捷方法 - 带上下文
func TraceWithContext(ctx context.Context, args ...interface{}) {
	GetDefaultLogger().WithContext(ctx).Trace(args...)
}

func DebugWithContext(ctx context.Context, args ...interface{}) {
	GetDefaultLogger().WithContext(ctx).Debug(args...)
}

func InfoWithContext(ctx context.Context, args ...interface{}) {
	GetDefaultLogger().WithContext(ctx).Info(args...)
}

func WarnWithContext(ctx context.Context, args ...interface{}) {
	GetDefaultLogger().WithContext(ctx).Warn(args...)
}

func ErrorWithContext(ctx context.Context, args ...interface{}) {
	GetDefaultLogger().WithContext(ctx).Error(args...)
}

func FatalWithContext(ctx context.Context, args ...interface{}) {
	GetDefaultLogger().WithContext(ctx).Fatal(args...)
}

// 全局便捷方法 - 带字段
func TraceWithFields(fields map[string]interface{}, args ...interface{}) {
	GetDefaultLogger().WithFields(fields).Trace(args...)
}

func DebugWithFields(fields map[string]interface{}, args ...interface{}) {
	GetDefaultLogger().WithFields(fields).Debug(args...)
}

func InfoWithFields(fields map[string]interface{}, args ...interface{}) {
	GetDefaultLogger().WithFields(fields).Info(args...)
}

func WarnWithFields(fields map[string]interface{}, args ...interface{}) {
	GetDefaultLogger().WithFields(fields).Warn(args...)
}

func ErrorWithFields(fields map[string]interface{}, args ...interface{}) {
	GetDefaultLogger().WithFields(fields).Error(args...)
}

func FatalWithFields(fields map[string]interface{}, args ...interface{}) {
	GetDefaultLogger().WithFields(fields).Fatal(args...)
}

// 全局便捷方法 - 带错误
func ErrorWithError(err error, args ...interface{}) {
	GetDefaultLogger().WithError(err).Error(args...)
}

func FatalWithError(err error, args ...interface{}) {
	GetDefaultLogger().WithError(err).Fatal(args...)
}

// 工具函数

// SetGlobalLevel 设置全局日志级别
func SetGlobalLevel(level LogLevel) {
	GetDefaultLogger().SetLevel(level)
}

// GetGlobalLevel 获取全局日志级别
func GetGlobalLevel() LogLevel {
	return GetDefaultLogger().GetLevel()
}

// Flush 刷新全局日志器
func Flush() error {
	return GetDefaultLogger().Flush()
}

// Close 关闭全局日志器
func Close() error {
	globalMutex.Lock()
	defer globalMutex.Unlock()

	if defaultLogger != nil {
		return defaultLogger.Close()
	}
	return nil
}

// StartTrace 开始追踪（全局方法）
func StartTrace(ctx context.Context, operationName string) (context.Context, *Span) {
	logger := GetDefaultLogger()
	if ixLogger, ok := logger.(*ixLogger); ok && ixLogger.traceManager != nil {
		return ixLogger.traceManager.StartTrace(ctx, operationName)
	}

	// 如果没有追踪管理器，返回简单的上下文
	traceCtx := &TraceContext{
		TraceID: generateTraceID(),
		SpanID:  generateSpanID(),
		Baggage: make(map[string]interface{}),
	}

	span := &Span{
		TraceID:       traceCtx.TraceID,
		SpanID:        traceCtx.SpanID,
		OperationName: operationName,
		StartTime:     time.Now(),
		Tags:          make(map[string]interface{}),
		Sampled:       true,
	}

	ctx = WithTraceContext(ctx, traceCtx)
	return ctx, span
}

// StartChildTrace 开始子追踪（全局方法）
func StartChildTrace(ctx context.Context, operationName string) (context.Context, *Span) {
	logger := GetDefaultLogger()
	if ixLogger, ok := logger.(*ixLogger); ok && ixLogger.traceManager != nil {
		return ixLogger.traceManager.StartChildSpan(ctx, operationName)
	}

	// 简单实现
	parentCtx := GetTraceContext(ctx)
	if parentCtx == nil {
		return StartTrace(ctx, operationName)
	}

	traceCtx := &TraceContext{
		TraceID:      parentCtx.TraceID,
		SpanID:       generateSpanID(),
		ParentSpanID: parentCtx.SpanID,
		Baggage:      parentCtx.Baggage,
	}

	span := &Span{
		TraceID:       traceCtx.TraceID,
		SpanID:        traceCtx.SpanID,
		ParentSpanID:  traceCtx.ParentSpanID,
		OperationName: operationName,
		StartTime:     time.Now(),
		Tags:          make(map[string]interface{}),
		Sampled:       true,
	}

	ctx = WithTraceContext(ctx, traceCtx)
	return ctx, span
}

// FinishTrace 结束追踪（全局方法）
func FinishTrace(span *Span) {
	if span == nil {
		return
	}

	logger := GetDefaultLogger()
	if ixLogger, ok := logger.(*ixLogger); ok && ixLogger.traceManager != nil {
		ixLogger.traceManager.FinishSpan(span)
	} else {
		// 简单实现
		span.EndTime = time.Now()
		span.Duration = span.EndTime.Sub(span.StartTime)
	}
}

// 预设配置函数

// NewDevelopmentLogger 创建开发环境日志器
func NewDevelopmentLogger() (Logger, error) {
	return NewLogger(
		WithLevel(DEBUG),
		WithFormat(TextFormat),
		WithColor(true),
		WithCaller(true),
		WithConsoleOutput(true),
		WithTrace(true, 5, 1.0),
		WithAppInfo("dev-app", "development"),
	)
}

// NewProductionLogger 创建生产环境日志器
func NewProductionLogger(appName, logFile string) (Logger, error) {
	return NewLogger(
		WithLevel(INFO),
		WithFormat(JSONFormat),
		WithColor(false),
		WithCaller(false),
		WithConsoleOutput(false),
		WithFileOutput(logFile,
			WithRotation(BothRotation),
			WithMaxSize(100),
			WithMaxAge(30),
			WithCompress(true),
		),
		WithTrace(true, 3, 0.1), // 10%采样率
		WithAppInfo(appName, "production"),
		WithSanitize(true, DefaultSanitizeFields(), DefaultSanitizePatterns()),
	)
}

// NewTestLogger 创建测试环境日志器
func NewTestLogger() (Logger, error) {
	return NewLogger(
		WithLevel(WARN),
		WithFormat(TextFormat),
		WithColor(false),
		WithCaller(true),
		WithConsoleOutput(true),
		WithTrace(false, 0, 0),
		WithAppInfo("test-app", "test"),
	)
}

// NewFileLogger 创建文件日志器
func NewFileLogger(filePath string, level LogLevel) (Logger, error) {
	// 确保目录存在
	dir := filepath.Dir(filePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return nil, fmt.Errorf("创建目录失败: %w", err)
	}

	return NewLogger(
		WithLevel(level),
		WithFormat(TextFormat),
		WithCaller(true),
		WithFileOutput(filePath,
			WithRotation(SizeRotation),
			WithMaxSize(50),
			WithMaxAge(7),
			WithCompress(true),
		),
	)
}

// NewNetworkLogger 创建网络日志器
func NewNetworkLogger(network, address string, level LogLevel) (Logger, error) {
	return NewLogger(
		WithLevel(level),
		WithFormat(JSONFormat),
		WithNetworkOutput(network, address, 10*time.Second),
	)
}

// 实用工具函数

// LoggerFromContext 从上下文获取日志器
func LoggerFromContext(ctx context.Context) Logger {
	if logger := GetTraceLogger(ctx); logger != nil {
		return logger
	}
	return GetDefaultLogger()
}

// WithTraceLogger 为上下文添加带追踪的日志器
func WithTraceLoggerContext(ctx context.Context, logger Logger) context.Context {
	return WithTraceLogger(ctx, logger)
}

// TraceFunction 追踪函数执行
func TraceFunction(ctx context.Context, functionName string, fn func(context.Context) error) error {
	ctx, span := StartTrace(ctx, functionName)
	defer FinishTrace(span)

	span.SetTag("function.name", functionName)

	logger := LoggerFromContext(ctx)
	logger.Tracef("开始执行函数: %s", functionName)

	err := fn(ctx)

	if err != nil {
		span.SetError(err)
		logger.WithError(err).Errorf("函数执行失败: %s", functionName)
	} else {
		logger.Tracef("函数执行成功: %s", functionName)
	}

	return err
}

// TraceMethod 追踪方法执行
func TraceMethod(ctx context.Context, receiver, method string, fn func(context.Context) error) error {
	operationName := fmt.Sprintf("%s.%s", receiver, method)
	return TraceFunction(ctx, operationName, fn)
}

// LogPanic 记录panic信息
func LogPanic(recovered interface{}) {
	if recovered != nil {
		logger := GetDefaultLogger()
		stack := GetCallStack(2, 10)

		logger.WithFields(map[string]interface{}{
			"panic":      recovered,
			"call_stack": stack,
		}).Fatal("程序发生panic")
	}
}

// SafeGo 安全的goroutine启动
func SafeGo(ctx context.Context, name string, fn func(context.Context)) {
	go func() {
		defer func() {
			if recovered := recover(); recovered != nil {
				logger := LoggerFromContext(ctx)
				logger.WithFields(map[string]interface{}{
					"goroutine": name,
					"panic":     recovered,
					"stack":     GetCallStack(2, 10),
				}).Error("goroutine发生panic")
			}
		}()

		logger := LoggerFromContext(ctx)
		logger.Tracef("启动goroutine: %s", name)

		fn(ctx)

		logger.Tracef("goroutine结束: %s", name)
	}()
}

// MeasureTime 测量执行时间
func MeasureTime(ctx context.Context, operation string, fn func()) {
	start := time.Now()
	defer func() {
		duration := time.Since(start)
		LoggerFromContext(ctx).WithFields(map[string]interface{}{
			"operation":   operation,
			"duration":    duration.String(),
			"duration_ms": duration.Milliseconds(),
		}).Info("操作执行时间")
	}()

	fn()
}

// LogHTTPRequest 记录HTTP请求
func LogHTTPRequest(ctx context.Context, method, url string, statusCode int, duration time.Duration) {
	level := INFO
	if statusCode >= 400 {
		level = WARN
	}
	if statusCode >= 500 {
		level = ERROR
	}

	logger := LoggerFromContext(ctx)
	fields := map[string]interface{}{
		"http.method":      method,
		"http.url":         url,
		"http.status_code": statusCode,
		"http.duration":    duration.String(),
		"http.duration_ms": duration.Milliseconds(),
	}

	if ixLogger, ok := logger.(*ixLogger); ok {
		ixLogger.log(level, fmt.Sprintf("HTTP %s %s %d", method, url, statusCode), fields, nil, ctx)
	} else {
		switch level {
		case TRACE:
			logger.WithFields(fields).Trace(fmt.Sprintf("HTTP %s %s %d", method, url, statusCode))
		case DEBUG:
			logger.WithFields(fields).Debug(fmt.Sprintf("HTTP %s %s %d", method, url, statusCode))
		case INFO:
			logger.WithFields(fields).Info(fmt.Sprintf("HTTP %s %s %d", method, url, statusCode))
		case WARN:
			logger.WithFields(fields).Warn(fmt.Sprintf("HTTP %s %s %d", method, url, statusCode))
		case ERROR:
			logger.WithFields(fields).Error(fmt.Sprintf("HTTP %s %s %d", method, url, statusCode))
		case FATAL:
			logger.WithFields(fields).Fatal(fmt.Sprintf("HTTP %s %s %d", method, url, statusCode))
		}
	}
}

// LogDBQuery 记录数据库查询
func LogDBQuery(ctx context.Context, query string, duration time.Duration, err error) {
	logger := LoggerFromContext(ctx)

	fields := map[string]interface{}{
		"db.query":       query,
		"db.duration":    duration.String(),
		"db.duration_ms": duration.Milliseconds(),
	}

	if err != nil {
		logger.WithFields(fields).WithError(err).Error("数据库查询失败")
	} else {
		logger.WithFields(fields).Debug("数据库查询完成")
	}
}

// LogCacheOperation 记录缓存操作
func LogCacheOperation(ctx context.Context, operation, key string, hit bool, duration time.Duration) {
	logger := LoggerFromContext(ctx)

	logger.WithFields(map[string]interface{}{
		"cache.operation": operation,
		"cache.key":       key,
		"cache.hit":       hit,
		"cache.duration":  duration.String(),
	}).Debug("缓存操作")
}

// LogExternalCall 记录外部调用
func LogExternalCall(ctx context.Context, service, method string, duration time.Duration, err error) {
	logger := LoggerFromContext(ctx)

	fields := map[string]interface{}{
		"external.service":  service,
		"external.method":   method,
		"external.duration": duration.String(),
	}

	if err != nil {
		logger.WithFields(fields).WithError(err).Error("外部调用失败")
	} else {
		logger.WithFields(fields).Info("外部调用成功")
	}
}

// 配置辅助函数

// ParseLevelFromString 从字符串解析日志级别
func ParseLevelFromString(level string) (LogLevel, error) {
	switch strings.ToUpper(level) {
	case "TRACE":
		return TRACE, nil
	case "DEBUG":
		return DEBUG, nil
	case "INFO":
		return INFO, nil
	case "WARN", "WARNING":
		return WARN, nil
	case "ERROR":
		return ERROR, nil
	case "FATAL":
		return FATAL, nil
	default:
		return INFO, fmt.Errorf("无效的日志级别: %s", level)
	}
}

// ParseFormatFromString 从字符串解析输出格式
func ParseFormatFromString(format string) (OutputFormat, error) {
	switch strings.ToLower(format) {
	case "text", "txt":
		return TextFormat, nil
	case "json":
		return JSONFormat, nil
	case "custom":
		return CustomFormat, nil
	default:
		return TextFormat, fmt.Errorf("无效的输出格式: %s", format)
	}
}

// GetLogFilePath 获取日志文件路径
func GetLogFilePath(appName, logDir string, level LogLevel) string {
	if logDir == "" {
		logDir = "logs"
	}

	filename := fmt.Sprintf("%s_%s.log", appName, strings.ToLower(level.String()))
	return filepath.Join(logDir, filename)
}

// EnsureLogDir 确保日志目录存在
func EnsureLogDir(logDir string) error {
	return os.MkdirAll(logDir, 0755)
}

// 性能监控

// LoggerStats 日志器统计信息
type LoggerStats struct {
	TotalLogs     int64     `json:"total_logs"`
	ErrorLogs     int64     `json:"error_logs"`
	DroppedLogs   int64     `json:"dropped_logs"`
	BufferUsage   float64   `json:"buffer_usage"`
	LastFlushTime time.Time `json:"last_flush_time"`
}

// GetGlobalStats 获取全局日志器统计
func GetGlobalStats() *LoggerStats {
	logger := GetDefaultLogger()
	if ixLogger, ok := logger.(*ixLogger); ok {
		stats := ixLogger.GetStats()
		return &LoggerStats{
			TotalLogs:     stats.TotalEntries,
			ErrorLogs:     stats.ErrorCount,
			DroppedLogs:   stats.DroppedEntries,
			BufferUsage:   float64(stats.BufferUsage) / float64(stats.BufferSize),
			LastFlushTime: stats.LastFlush,
		}
	}

	return &LoggerStats{}
}

// 调试工具

// EnableDebugMode 启用调试模式
func EnableDebugMode() {
	SetGlobalLevel(DEBUG)

	logger := GetDefaultLogger()
	logger.AddHook(NewConsoleHook([]LogLevel{DEBUG, TRACE}, false))
}

// EnableTraceMode 启用追踪模式
func EnableTraceMode() {
	SetGlobalLevel(TRACE)

	logger := GetDefaultLogger()
	logger.AddHook(NewConsoleHook([]LogLevel{TRACE}, false))
}

// DisableDebugMode 禁用调试模式
func DisableDebugMode() {
	SetGlobalLevel(INFO)
}

// 中间件和装饰器

// LoggerMiddleware 日志中间件接口
type LoggerMiddleware interface {
	Handle(ctx context.Context, next func(context.Context) error) error
}

// TracingMiddleware 追踪中间件
type TracingMiddleware struct {
	operationName string
}

// NewTracingMiddleware 创建追踪中间件
func NewTracingMiddleware(operationName string) *TracingMiddleware {
	return &TracingMiddleware{
		operationName: operationName,
	}
}

// Handle 处理请求
func (m *TracingMiddleware) Handle(ctx context.Context, next func(context.Context) error) error {
	ctx, span := StartTrace(ctx, m.operationName)
	defer FinishTrace(span)

	err := next(ctx)
	if err != nil {
		span.SetError(err)
	}

	return err
}

// LoggingMiddleware 日志中间件
type LoggingMiddleware struct {
	level LogLevel
}

// NewLoggingMiddleware 创建日志中间件
func NewLoggingMiddleware(level LogLevel) *LoggingMiddleware {
	return &LoggingMiddleware{
		level: level,
	}
}

// Handle 处理请求
func (m *LoggingMiddleware) Handle(ctx context.Context, next func(context.Context) error) error {
	start := time.Now()

	logger := LoggerFromContext(ctx)
	if ixLogger, ok := logger.(*ixLogger); ok {
		ixLogger.log(m.level, "请求开始", nil, nil, ctx)
	} else {
		switch m.level {
		case TRACE:
			logger.Trace("请求开始")
		case DEBUG:
			logger.Debug("请求开始")
		case INFO:
			logger.Info("请求开始")
		case WARN:
			logger.Warn("请求开始")
		case ERROR:
			logger.Error("请求开始")
		case FATAL:
			logger.Fatal("请求开始")
		}
	}

	err := next(ctx)

	duration := time.Since(start)
	fields := map[string]interface{}{
		"duration":    duration.String(),
		"duration_ms": duration.Milliseconds(),
	}

	if err != nil {
		logger.WithFields(fields).WithError(err).Error("请求失败")
	} else {
		logger.WithFields(fields).Info("请求完成")
	}

	return err
}
